﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using CamShared;
using System.Diagnostics;

namespace UPnP
{
    public class UPnPDeviceHost
    {
        public List<Device> Devices = new List<Device>();
        internal Socket sock = null;

        UdpClient udp = null;
        IPEndPoint groupEP = null;

        public void Activate()
        {
            try
            {
                groupEP = new IPEndPoint(IPAddress.Any, 1900);
                udp = new UdpClient();
                udp.Client.Bind(groupEP);
                Thread t = new Thread(SocketMon);
                t.Start();
            }
            catch (Exception ex)
            {
                Trace.WriteLine("UDP Activation Error: " + ex);
            }
        }

        private void SocketMon()
        {
            Thread.CurrentThread.Name = "UPnP Device Host";
            try
            {
                byte[] buffer = null;
                do
                {
                    buffer = udp.Receive(ref groupEP);

                    if (buffer != null && buffer.Length > 0)
                    {
                        OnResponse(Encoding.ASCII.GetString(buffer, 0, buffer.Length), groupEP);
                    }
                } while (buffer != null && buffer.Length > 0);
            }
            catch (SocketException aex)
            {
                Trace.WriteLine("UPnP Device Host SE: " + aex);
                Thread.Sleep(1000);
                SocketMon();
            }
            catch (Exception ex)
            {
                Trace.WriteLine("UPnP Device Host: " + ex);
            }

        }

        private void OnResponse(string req, IPEndPoint host)
        {
            try
            {
                Message msg = new Message(req);
                if (msg.RequestLine == "HTTP/1.1 200 OK")
                {
                    // response from search
                }
                else if (msg.RequestLine == "NOTIFY * HTTP/1.1")
                {
                    // notification of ssdp:alive
                }
                else if (msg.RequestLine == "M-SEARCH * HTTP/1.1")
                {
                    // search
                    Trace.WriteLine("SSDP Discovery from " + host + " (Responding for " + Devices.Count + " devices)");

                    foreach (Device d in Devices.ToArray())
                    {
                        try
                        {
                            byte[] data = Encoding.ASCII.GetBytes(d.ToSSDPResponse());
                            udp.Send(data, data.Length, groupEP);
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine("Error sending for device: " + ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Error in UPnP/DevHost OnResponse: " + ex);
            }
        }
    }
}
